using System;
using System.Reflection;
using System.Text;

namespace Glpt.Common
{
    /// <summary>
    /// 动态实例化操作类
    /// </summary>
    public class InvokeDynamic
    {
        /// <summary>
        /// 动态调用DLL时获取Dll路径
        /// </summary>
        /// <param name="forwarddll">DLL字符串</param>
        /// <returns>Dll路径</returns>
        public static string GetDllLib(string forwarddll)
        {
            String filename = forwarddll;
            int index = filename.IndexOf('?');
            if (index >= 0) filename = filename.Substring(0, index);
            if (filename.Length > 0 && filename.IndexOf(':') < 0) filename = Funcs.AppPath + filename;
            return filename;
        }

        /// <summary>
        /// 检测DLL是否存在
        /// </summary>
        /// <param name="forwarddll">DLL字符串</param>
        /// <returns>是否存在</returns>
        public static bool CheckExists(string forwarddll)
        {
            return System.IO.File.Exists(GetDllLib(forwarddll));
        }

        /// <summary>
        /// 动态调用DLL时获取对象名称
        /// </summary>
        /// <param name="forwarddll">DLL字符串</param>
        /// <returns>对象名称</returns>
        public static string GetClassName(string forwarddll)
        {
            String classname = forwarddll;
            int index = classname.IndexOf('?');
            classname = classname.Substring(index + 1);
            return classname;
        }

        /// <summary>
        /// 动态调用DLL时获取初始化参数
        /// </summary>
        /// <param name="classparams">参数列表</param>
        /// <returns>参数列表</returns>
        public static object[] GetExecParams(string classparams)
        {
            if (string.IsNullOrEmpty(classparams)) return null;
            string[] execparams = new string[0];
            if (classparams.Length > 0) execparams = classparams.Split(new char[] { ',' });
            return execparams;
        }

        /// <summary>
        /// 动态实例化对象
        /// </summary>
        /// <param name="forwarddll">动态调用对象字符串</param>
        /// <returns>动态创建的对象</returns>
        public static object CreateObject(string forwarddll)
        {
            return CreateObject(forwarddll, null);
        }

        /// <summary>
        /// 执行进程
        /// </summary>
        /// <param name="forwardexe">可执行程序路径</param>
        /// <param name="exec_params">参数列表</param>
        /// <returns>执行结果</returns>
        public static void InvokeProcess(string forwardexe, string arguments)
        {
            System.Diagnostics.Process p = new System.Diagnostics.Process();
            p.StartInfo.FileName = forwardexe;
            p.StartInfo.Arguments = arguments;
            p.StartInfo.UseShellExecute = false;
            p.Start();
            p.Close();
        }

        /// <summary>
        /// 调用EXE命令
        /// </summary>
        /// <param name="filename">路径</param>
        /// <param name="arguments">参数</param>
        /// <returns></returns>
        public static string InvokeEXE(string forwardexe, string arguments)
        {
            System.Diagnostics.Process p = new System.Diagnostics.Process();
            p.StartInfo = new System.Diagnostics.ProcessStartInfo();
            p.StartInfo.FileName = forwardexe;
            p.StartInfo.Arguments = arguments;
            p.StartInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
            p.StartInfo.RedirectStandardOutput = true;
            p.StartInfo.UseShellExecute = false;
            p.StartInfo.CreateNoWindow = true;
            p.Start();
            System.IO.StreamReader sr = p.StandardOutput;
            string info = "";
            StringBuilder sb = new StringBuilder();
            while ((info = sr.ReadLine()) != null)
            {
                sb.AppendLine(info);
                if (sr.EndOfStream) break;
            }
            return sb.ToString();
        }
        /// <summary>
        /// 调用EXE命令
        /// </summary>
        /// <param name="filename">路径</param>
        /// <param name="arguments">参数</param>
        public static void InvokeEXEStart(string forwardexe, string arguments)
        {
            System.Diagnostics.Process p = new System.Diagnostics.Process();
            p.StartInfo = new System.Diagnostics.ProcessStartInfo();
            p.StartInfo.FileName = forwardexe;
            p.StartInfo.Arguments = arguments;
            p.StartInfo.CreateNoWindow = true;
            p.Start();
        }
        /// <summary>
        /// 调用CMD命令
        /// </summary>
        /// <param name="arguments">参数列表</param>
        /// <returns>执行结果</returns>
        public static string InvokeCMD(string arguments)
        {
            return InvokeCMD(arguments, null);
        }
        /// <summary>
        /// 调用CMD命令
        /// </summary>
        /// <param name="arguments">参数列表</param>
        /// <returns>执行结果</returns>
        public static string InvokeCMD(string arguments, string[] cmd2)
        {
            System.Diagnostics.Process p = new System.Diagnostics.Process();
            p.StartInfo.FileName = "cmd.exe";
            p.StartInfo.UseShellExecute = false;
            p.StartInfo.RedirectStandardInput = true;
            p.StartInfo.RedirectStandardOutput = true;
            p.StartInfo.RedirectStandardError = true;
            p.StartInfo.CreateNoWindow = true;
            p.Start();
            if (arguments.Length > 0) p.StandardInput.WriteLine(arguments);
            if (cmd2 != null)
            {
                foreach (string argcmd in cmd2)
                {
                    if (argcmd.Length > 0)
                    {
                        p.StandardInput.WriteLine(argcmd);
                        if (arguments.Length == 0) arguments = argcmd;
                    }
                }
            }
            p.StandardInput.WriteLine("exit");
            p.WaitForExit();
            string sret = p.StandardOutput.ReadToEnd();
            p.Close();
            string[] log_msg = sret.Split(new string[] { Glpt.Data.DataFuns.NewLineString }, StringSplitOptions.RemoveEmptyEntries);
            StringBuilder sb = new StringBuilder();
            bool is_begin = false;
            foreach (string msg in log_msg)
            {
                if (msg.EndsWith(">exit"))
                    break;
                else if (msg.EndsWith(arguments) && !is_begin)
                    is_begin = true;
                else if (is_begin)
                    sb.AppendLine(msg);
            }
            return sb.ToString().TrimEnd();
        }

        /// <summary>
        /// 动态实例化对象
        /// </summary>
        /// <param name="forwarddll">动态调用对象字符串</param>
        /// <param name="classparams">参数列表</param>
        /// <returns>动态创建的对象</returns>
        public static object CreateObject(string forwarddll, string classparams)
        {
            string dlllib = GetDllLib(forwarddll);
            string classname = GetClassName(forwarddll);
            object obj = null;
            Assembly asm = null;
            if (dlllib.Length == 0)
                asm = Assembly.GetExecutingAssembly();
            else
                asm = Assembly.LoadFile(dlllib);
            if (classname.Length == 0) throw new Exception("对象名称配置错误!");
            Type type = asm.GetType(classname);
            if (type != null)
            {
                try
                {
                    obj = Activator.CreateInstance(type);
                }
                catch (Exception ivkerr)
                {
                    throw new Exception(ivkerr.InnerException.Message, ivkerr.InnerException);
                }
                if (classparams != null && classparams.Length > 0)
                    InvokeMember(obj, classparams);
            }
            else
                throw new Exception("未找到" + classname);
            return obj;
        }

        /// <summary>
        /// 动态调用对象
        /// </summary>
        /// <param name="obj">动态对象</param>
        /// <param name="classparams">参数列表</param>
        /// <returns>动态创建的对象</returns>
        public static object InvokeMember(object obj, string classparams)
        {
            return InvokeMember(obj, GetExecParams(classparams));
        }

        /// <summary>
        /// 动态调用对象
        /// </summary>
        /// <param name="obj">动态对象</param>
        /// <param name="execParams">参数列表</param>
        /// <returns>动态调用返回值</returns>
        public static object InvokeMember(object obj, object[] execParams)
        {
            if (execParams != null && execParams.Length == 1 && execParams[0] is OperateRight)
                return InvokeMember(obj, execParams, "SetOperateRight");
            else
                return InvokeMember(obj, execParams, "SetParams");
        }

        /// <summary>
        /// 动态调用对象
        /// </summary>
        /// <param name="obj">动态对象</param>
        /// <param name="execParams">参数列表</param>
        /// <param name="invokeMember">要执行的方法名</param>
        /// <returns>动态调用返回值</returns>
        public static object InvokeMember(object obj, object[] execParams, string invokeMember)
        {
            try
            {
                if (obj == null) return null;
                Type type = obj.GetType();
                if (invokeMember.Length > 0 && type.GetMember(invokeMember).Length > 0)
                {
                    return type.InvokeMember(invokeMember, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.InvokeMethod | BindingFlags.Static, null, obj, execParams);
                }
                else
                    return null;
            }
            catch (Exception ivkerr)
            {
                if (ivkerr.InnerException == null)
                    throw;
                else
                    throw new Exception(ivkerr.InnerException.Message, ivkerr.InnerException);
            }
        }

        /// <summary>
        /// 动态获取对象的属性值
        /// </summary>
        /// <param name="obj">对象名</param>
        /// <param name="propertyName">属性名</param>
        /// <returns>属性值</returns>
        public static object GetPropertyInfo(object obj, string propertyName)
        {
            try
            {
                Type type = obj.GetType();
                PropertyInfo vPropertyInfo = type.GetProperty(propertyName);
                if (vPropertyInfo != null)
                    return vPropertyInfo.GetValue(obj, null);
                else
                    return null;
            }
            catch (Exception ivkerr)
            {
                if (ivkerr.InnerException == null)
                    throw;
                else
                    throw new Exception(ivkerr.InnerException.Message, ivkerr.InnerException);
            }
        }

        /// <summary>
        /// 动态设置对象的属性值
        /// </summary>
        /// <param name="obj">对象名</param>
        /// <param name="propertyName">属性名</param>
        /// <param name="value">属性值</param>
        /// <returns>是否设置成功</returns>
        public static bool SetPropertyInfo(object obj, string propertyName, object value)
        {
            try
            {
                Type type = obj.GetType();
                PropertyInfo vPropertyInfo = type.GetProperty(propertyName);
                if (vPropertyInfo != null)
                {
                    vPropertyInfo.SetValue(obj, value, null);
                    return true;
                }
            }
            catch (Exception ivkerr)
            {
                if (ivkerr.InnerException == null)
                    throw;
                else
                    throw new Exception(ivkerr.InnerException.Message, ivkerr.InnerException);
            }
            return false;
        }

        /// <summary>
        /// 获取类的指定类型的属性成员
        /// </summary>
        /// <param name="type">指定类型</param>
        /// <param name="rettype">属性的返回值类型</param>
        /// <returns>属性成员名称列表</returns>
        public static string[] GetMembers(Type type, Type rettype)
        {
            if (type.IsEnum) return type.GetEnumNames();
            MemberInfo[] mis = type.GetMembers(BindingFlags.Public | BindingFlags.Static);
            int icount = 0;
            for (int i = 0; i < mis.Length; i++)
            {
                if (mis[i].ToString().StartsWith(rettype.FullName))
                    if (mis[i].Name.StartsWith("get_"))
                        icount++;
            }
            string[] ret = new string[icount];
            for (int i = 0, idx = 0; i < mis.Length; i++)
            {
                if (mis[i].ToString().StartsWith(rettype.FullName))
                    if (mis[i].Name.StartsWith("get_"))
                        ret[idx++] = mis[i].Name.Substring(4);
            }
            return ret;
        }
        /// <summary>
        /// 获取举类型的值和名称
        /// </summary>
        /// <param name="enumType">枚举类型</param>
        /// <returns>数据表</returns>
        public static System.Data.DataTable GetEnumTable(Type enumType)
        {
            return GetEnumTable(enumType, typeof(int));
        }
        /// <summary>
        /// 获取举类型的值和名称
        /// </summary>
        /// <param name="enumType">枚举类型</param>
        /// <param name="valueType">值类型</param>
        /// <returns>数据表</returns>
        public static System.Data.DataTable GetEnumTable(Type enumType, Type valueType)
        {
            if (!enumType.IsEnum)
                throw new ArgumentException("enumType必须是枚举类型");
            var values = Enum.GetValues(enumType);
            System.Data.DataTable dt = new System.Data.DataTable();
            dt.Columns.Add("Value", valueType);
            dt.Columns.Add("Text");
            foreach (var val in values)
            {
                dt.Rows.Add(new object[] { val, Enum.GetName(enumType, val) });
            }
            return dt;
        }
    }
}
